package t5750.netty.websocket.chat;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.URISyntaxException;
import java.net.URL;

import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedNioFile;

/**
 * 处理 Http 请求
 */
public class HttpRequestHandler extends
		SimpleChannelInboundHandler<FullHttpRequest> { // 1
	private final String wsUri;
	private static final File INDEX;
	static {
		URL location = HttpRequestHandler.class.getProtectionDomain()
				.getCodeSource().getLocation();
		try {
			String path = location.toURI().toString()
					.replace("classes", "resources")
					+ "templates"
					+ File.separatorChar
					+ "websocketChatClient.html";
			path = !path.contains("file:") ? path : path.substring(5);
			INDEX = new File(path);
		} catch (URISyntaxException e) {
			throw new IllegalStateException(
					"Unable to locate websocketChatClient.html", e);
		}
	}

	public HttpRequestHandler(String wsUri) {
		this.wsUri = wsUri;
	}

	@Override
	public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request)
			throws Exception {
		if (wsUri.equalsIgnoreCase(request.getUri())) {
			ctx.fireChannelRead(request.retain()); // 2
		} else {
			if (HttpHeaders.is100ContinueExpected(request)) {
				send100Continue(ctx); // 3
			}
			RandomAccessFile file = new RandomAccessFile(INDEX, "r");// 4
			HttpResponse response = new DefaultHttpResponse(
					request.getProtocolVersion(), HttpResponseStatus.OK);
			response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
					"text/html; charset=UTF-8");
			boolean keepAlive = HttpHeaders.isKeepAlive(request);
			if (keepAlive) { // 5
				response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
						file.length());
				response.headers().set(HttpHeaders.Names.CONNECTION,
						HttpHeaders.Values.KEEP_ALIVE);
			}
			ctx.write(response); // 6
			if (ctx.pipeline().get(SslHandler.class) == null) { // 7
				ctx.write(new DefaultFileRegion(file.getChannel(), 0, file
						.length()));
			} else {
				ctx.write(new ChunkedNioFile(file.getChannel()));
			}
			ChannelFuture future = ctx
					.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); // 8
			if (!keepAlive) {
				future.addListener(ChannelFutureListener.CLOSE); // 9
			}
			file.close();
		}
	}

	private static void send100Continue(ChannelHandlerContext ctx) {
		FullHttpResponse response = new DefaultFullHttpResponse(
				HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
		ctx.writeAndFlush(response);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		Channel incoming = ctx.channel();
		System.out.println("Client:" + incoming.remoteAddress() + "异常");
		// 当出现异常就关闭连接
		cause.printStackTrace();
		ctx.close();
	}
}